package com.neo.tiny.admin.controller.sys;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.neo.tiny.admin.service.sys.SysMenuService;
import com.neo.tiny.admin.service.sys.SysRoleMenuService;
import com.neo.tiny.admin.vo.menu.SysMenuVO;
import com.neo.tiny.common.constant.CacheConstants;
import com.neo.tiny.common.common.ResResult;
import com.neo.tiny.admin.entity.sys.SysMenu;
import com.neo.tiny.admin.entity.sys.SysRoleMenu;
import com.neo.tiny.secrity.util.SecurityUtils;
import com.neo.tiny.service.RedisService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description: 菜单控制器
 * @Author: yqz
 * @CreateDate: 2022/8/7 19:30
 */

@Slf4j
@RestController
@RequestMapping("/admin/menu")
@Api(tags = "菜单管理模块")
public class SysMenuController {

    @Autowired
    private SysMenuService menuService;

    @Autowired
    private SysRoleMenuService roleMenuService;

    @Autowired
    private RedisService redisService;

    @ApiOperation("新增菜单")
    @PostMapping("/add")
    public ResResult<Boolean> save(@Valid @RequestBody SysMenuVO vo) {

        log.info("新增菜单入参：{}", vo);

        return ResResult.success(menuService.save(BeanUtil.copyProperties(vo, SysMenu.class)));
    }


    /**
     * 返回当前用户的树形菜单集合
     *
     * @param parentId 父节点ID
     * @return 当前用户的树形菜单
     */
    @ApiOperation("返回当前用户的树形菜单集合")
    @GetMapping("/list-menu")
    public ResResult<List<Tree<Long>>> getUserMenu(Long parentId) {
        // 获取符合条件的菜单

        List<SysMenuVO> menuList = SecurityUtils.getUser().getMenuList();

        return ResResult.success(menuService.filterMenu(menuList, parentId));
    }

    /**
     * 返回树形菜单集合
     *
     * @param lazy     是否是懒加载
     * @param parentId 父节点ID
     * @return 树形菜单
     */
    @ApiOperation("返回树形菜单集合")
    @GetMapping(value = "/tree")
    public ResResult<List<Tree<Long>>> getTree(boolean lazy, Long parentId) {
        return ResResult.success(menuService.treeMenu(lazy, parentId));
    }

    @ApiOperation("根据角色id返回树形菜单集合")
    @GetMapping(value = "/tree/{roleId}")
    public ResResult<Set<Long>> getTreeByRoleId(@PathVariable("roleId") Long roleId) {

        List<SysRoleMenu> list = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));

        return ResResult.success(list.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toSet()));
    }

    /**
     * 通过ID查询菜单的详细信息
     * //使用正则指定Id为数字
     *
     * @param id 菜单ID
     * @return 菜单详细信息
     */
    @ApiOperation("通过ID查询菜单的详细信息")
    @GetMapping("/getMenuById/{id:\\d+}")
    public ResResult<SysMenuVO> getById(@PathVariable Long id) {
        return ResResult.success(BeanUtil.copyProperties(menuService.getById(id), SysMenuVO.class));
    }

    /**
     * 更新菜单
     *
     * @param vo
     * @return
     */
    @ApiOperation("更新菜单")
    @PostMapping("/update")
    public ResResult<Boolean> update(@Valid @RequestBody SysMenuVO vo) {

        SysMenu sysMenu = BeanUtil.copyProperties(vo, SysMenu.class);
        boolean res = menuService.updateById(sysMenu);

        // 菜单有变动，需清空缓存
        if (res) {
            Set<String> keys = redisService.keys(CacheConstants.USER_DETAILS + StrUtil.COLON + CacheConstants.CACHE_PATTERN_PREFIX);
            redisService.del(keys);
        }
        return ResResult.success(res);
    }


    @ApiOperation("删除菜单")
    @DeleteMapping("/del/{menuId}")
    public ResResult<Boolean> delete(@PathVariable("menuId") Long menuId) {

        // 查询该菜单下的子菜单
        long count = menuService.count(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, menuId));
        Assert.isTrue(count <= 0, "菜单存在下级节点");

        roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getMenuId, menuId));

        return ResResult.success(menuService.removeById(menuId));

    }


}
